(function() {
	var log = panda.log("panda.monit");

	var imp, fs, enAdd, enMod, enOver;
	importer();
	shortcuts();

	panda.monit = function(dirs, callback) {
		var watcher, paths;
		watcher = fs.newWatchService();
		paths = imp.HashMap();

		panda.each(dirs, function(dir) { add(imp.File(dir)); });

		imp.Thread(run).start();

		function add(dir) {
			var path, key;
			path = dir.toPath();
			key = path.register(watcher, enAdd, enMod);
			paths.put(key, path);

			panda.each(dir.listFiles(), function(file){
				file.directory && add(file)
			});
		}

		function run() {
			while (true) {
				try {
					doRun();
				} catch (e) {
					log.error("File Monit Error: " + e, e.javaException);
				}
			}
		}

		function doRun() {
			var key = watcher.take();
			each(key.pollEvents(), function(e){
				var path, file;
				if (e.kind() === enOver) { return; }

				path = paths.get(key);
				file = path.resolve(e.context());

				callback(file);
			});

			key.reset();
		}
	};

	function importer() {
		imp = JavaImporter(
			java.io,
			java.lang,
			java.nio.file,
			java.util);
	}

	function shortcuts() {
		fs = imp.FileSystems.getDefault();
		var kinds = imp.StandardWatchEventKinds;
		enAdd = kinds.ENTRY_CREATE;
		enMod = kinds.ENTRY_MODIFY;
		enOver = kinds.OVERFLOW;
	}

	function each(list, callback) {
		var i = 0, l = list.size();
		while (i < l) { callback(list.get(i++)); }
	}
}());
